package com.ibeeking.found.cop.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.enums.SyncStatusEnum;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.cop.b.rest.service.ICopSensitiveWordService;

import com.ibeeking.found.cop.b.rest.service.IMqService;
import com.ibeeking.found.cop.b.rest.service.IWxOpenService;
import com.ibeeking.found.cop.service.common.bo.CopSensitiveMatchWordBO;
import com.ibeeking.found.cop.service.common.dos.CopEmployeeDO;
import com.ibeeking.found.cop.service.common.dos.CopSensitiveWordDO;
import com.ibeeking.found.cop.service.common.enums.MqSyncOperatorTypeEnum;
import com.ibeeking.found.cop.service.common.param.CopSensitiveWordParam;

import com.ibeeking.found.cop.service.common.param.MqSyncCopParam;
import com.ibeeking.found.cop.service.common.query.CopSensitiveWordQuery;
import com.ibeeking.found.cop.service.common.vo.CopSensitiveWordVO;
import com.ibeeking.found.cop.service.mapper.CopEmployeeMapper;
import com.ibeeking.found.cop.service.mapper.CopSensitiveWordMapper;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.json.JsonUtils;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.external.interceptrule.ApplicableRange;
import me.chanjar.weixin.cp.bean.external.interceptrule.WxCpInterceptRule;
import me.chanjar.weixin.cp.bean.external.interceptrule.WxCpInterceptRuleAddRequest;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName CopSensitiveWordServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class CopSensitiveWordServiceImpl extends ServiceImpl<CopSensitiveWordMapper, CopSensitiveWordDO> implements ICopSensitiveWordService {

    @Resource
    private CopSensitiveWordMapper copSensitiveWordMapper;

    @Resource
    private CopEmployeeMapper copEmployeeMapper;

    @Resource
    private IWxOpenService wxOpenServiceImpl;

    @Resource
    private IMqService mqServiceImpl;

    @Override
    public List<CopSensitiveWordVO> list(CopSensitiveWordQuery query) {
        List<CopSensitiveWordDO> entityDOS = copSensitiveWordMapper.selectList(new LambdaQueryWrapper<CopSensitiveWordDO>()
                .eq(query.getId() != null, CopSensitiveWordDO::getId, query.getId())
                .like(StringUtils.isNotBlank(query.getName()), CopSensitiveWordDO::getName, query.getName())
                .eq(query.getStatus() != null, CopSensitiveWordDO::getStatus, query.getStatus())
                .orderByDesc(CopSensitiveWordDO::getCreateTime)
        );
        List<CopSensitiveWordVO> entityVOS =JsonUtils.jsonToList(entityDOS, CopSensitiveWordVO.class);
        entityVOS.forEach(x -> {
            String wordListJson = x.getWordList();
            if(StringUtils.isNotEmpty(wordListJson)){
                List<CopSensitiveMatchWordBO> matchWords = JsonUtils.jsonToList(wordListJson, CopSensitiveMatchWordBO.class);
                List<String> wordList = matchWords.parallelStream().map(CopSensitiveMatchWordBO::getWord).collect(Collectors.toList());
                if(Collections3.isNotEmpty(wordList)){
                    x.setWordListStr(StringUtils.join(wordList, ","));
                }
                x.setMatchWords(matchWords);
            }
            x.setSyncStatusDesc(SyncStatusEnum.getName(x.getSyncStatus()));
            x.setStatusDesc(PublishStatusEnum.getName(x.getStatus()));
        });
        return entityVOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(CopSensitiveWordParam param) {
        checkUnique(param);
        CopSensitiveWordDO entityDO = BeanUtil.convertBean(param, CopSensitiveWordDO.class);
        entityDO.setId(GenerateId.generateId());
        entityDO.setCreateBy(UserUtils.getUserId());
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());
        entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
        entityDO.setStatus(PublishStatusEnum.DISABLE.getValue());
        List<CopSensitiveMatchWordBO> matchWords = param.getMatchWords();
        if(Collections3.isNotEmpty(matchWords)){
            entityDO.setWordList(JsonUtils.toJsonStr(matchWords));
        }else{
            entityDO.setWordList(null);
        }
        return copSensitiveWordMapper.insert(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(CopSensitiveWordParam param) {
        CopSensitiveWordDO entityDO = BeanUtil.convertBean(param, CopSensitiveWordDO.class);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        List<CopSensitiveMatchWordBO> matchWords = param.getMatchWords();
        if(Collections3.isNotEmpty(matchWords)){
            entityDO.setWordList(JsonUtils.toJsonStr(matchWords));
        }else{
            entityDO.setWordList(null);
        }
        entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
        return copSensitiveWordMapper.updateById(entityDO) > 0;
    }

    @Override
    public CopSensitiveWordVO view(Long id) {
        CopSensitiveWordDO entityDO = copSensitiveWordMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        CopSensitiveWordVO entityVO = BeanUtil.convertBean(entityDO, CopSensitiveWordVO.class);
        if(entityVO != null) {
            String wordListStr = entityVO.getWordList();
            if(StringUtils.isNotEmpty(wordListStr)){
                List<CopSensitiveMatchWordBO> matchWords = JsonUtils.jsonToList(wordListStr, CopSensitiveMatchWordBO.class);
                List<String> wordList = matchWords.parallelStream().map(CopSensitiveMatchWordBO::getWord).collect(Collectors.toList());
                if(Collections3.isNotEmpty(wordList)){
                    entityVO.setWordListStr(StringUtils.join(wordList, ","));
                }
                entityVO.setMatchWords(matchWords);
            }
            entityVO.setStatusDesc(PublishStatusEnum.getName(entityDO.getStatus()));
            entityVO.setSyncStatusDesc(SyncStatusEnum.getName(entityDO.getSyncStatus()));
        }
        return entityVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        CopSensitiveWordDO entityDO = copSensitiveWordMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        entityDO.setStatus(status);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        return copSensitiveWordMapper.updateById(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        CopSensitiveWordDO entityDO = copSensitiveWordMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        if(entityDO.getSyncStatus() == SyncStatusEnum.SYNC_YES.getValue()) {
            Integer result = this.getBean().sendInstructionToMq(id, MqSyncOperatorTypeEnum.COP_SYNC_SENSITIVE_WORD_DEL.getCode());
            if (result <= 0) throw new BusinessException("同步删除企微的敏感词失败，请联系管理员！");
        }

        return copSensitiveWordMapper.deleteById(id) > 0;
    }
    /***
     *
     * 向Mq发送执行指令
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer sendInstructionToMq(Long id, String operType){
        String tenantId = UserUtils.getTenantId();
        MqSyncCopParam mqParam = new MqSyncCopParam();
        mqParam.setTenantId(Long.valueOf(tenantId));
        mqParam.setId(id);
        mqParam.setOperType(operType);
        mqServiceImpl.sendSyncToWxTaskMessage(mqParam);
        return 1;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer syncSensitiveWordToWxCp(Integer tenantId, Long id, Boolean deleted){
        CopSensitiveWordDO entityDO = copSensitiveWordMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        List<String> matchWord = new ArrayList<>();
        String wordListStr = entityDO.getWordList();
        if(StringUtils.isNotEmpty(wordListStr)){
            List<CopSensitiveMatchWordBO> copSensitiveMatchWordBOS = JsonUtils.jsonToList(wordListStr, CopSensitiveMatchWordBO.class);
            matchWord = Collections3.isNotEmpty(copSensitiveMatchWordBOS)?copSensitiveMatchWordBOS.stream().map(CopSensitiveMatchWordBO::getWord).collect(Collectors.toList()) :null;
        }
        String ruleId = entityDO.getRuleId();
        WxCpService wxCpService = wxOpenServiceImpl.getWxCpService(tenantId.longValue());
        WxCpConfigStorage wxCpConfigStorage = wxCpService.getWxCpConfigStorage();
        if (wxCpConfigStorage == null) {
            throw new BusinessException("获取企微服务失败!");
        }

//        String accessToken = wxOpenServiceImpl.getWxCpTpAccessToken(tenantId.longValue());
//        LogUtils.info(">>>>>>>>>accessToken is:{}",accessToken);
//        if(StringUtils.isNotEmpty(accessToken)){
//            wxCpConfigStorage.updateAccessToken(accessToken,1000);
//            wxCpService.setWxCpConfigStorage(wxCpConfigStorage);
//        }
        String corpId = wxCpConfigStorage.getCorpId();
        Integer agentId = wxCpConfigStorage.getAgentId();
        WxCpExternalContactService wxCpExternalContactService = wxCpService.getExternalContactService();
        if (wxCpExternalContactService == null) throw new BusinessException("获取企微服务外部联系人服务!");

        if(deleted){
            try {
                if(agentId == null) return 0;
                if (StringUtils.isEmpty(ruleId)) return 0;
                wxCpExternalContactService.delInterceptRule(ruleId);
                return 1;
            } catch (WxErrorException ex) {
                return 0;
            }
        }else {
            List<CopEmployeeDO> copEmployeeDOS = copEmployeeMapper.selectList(new LambdaQueryWrapper<>());
            List<String> employeeCodeList = Collections3.isNotEmpty(copEmployeeDOS)?copEmployeeDOS.stream().map(CopEmployeeDO::getEmployeeCode).collect(Collectors.toList()):null;
            if (StringUtils.isEmpty(ruleId)) {
                try {
                    WxCpInterceptRuleAddRequest wxCpInterceptRuleAddRequest = new WxCpInterceptRuleAddRequest();
                    wxCpInterceptRuleAddRequest.setRuleName(entityDO.getName());
                    if(Collections3.isEmpty(matchWord)) throw new BusinessException("没有敏感词设置，请先设置！");
                    if(Collections3.isEmpty(employeeCodeList)) throw new BusinessException("请先设置企业员工信息！");
                    wxCpInterceptRuleAddRequest.setWordList(matchWord);
                    wxCpInterceptRuleAddRequest.setInterceptType(2);
                    ApplicableRange applicableRange = new ApplicableRange();
                    applicableRange.setUserList(employeeCodeList);
                    wxCpInterceptRuleAddRequest.setApplicableRange(applicableRange);
                    String returnRuleId = wxCpExternalContactService.addInterceptRule(wxCpInterceptRuleAddRequest);
                    if (StringUtils.isNotEmpty(returnRuleId)) {
                        entityDO.setRuleId(returnRuleId);
                        entityDO.setSyncStatus(SyncStatusEnum.SYNC_YES.getValue());
                    } else {
                        entityDO.setRuleId(null);
                        entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
                    }
                } catch (WxErrorException ex) {
                    LogUtils.error("同步敏感词出错" + ex);
                    entityDO.setRuleId(null);
                    entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
                }
            } else {
                try {
                    WxCpInterceptRule wxCpInterceptRule = new WxCpInterceptRule();
                    wxCpInterceptRule.setRuleId(entityDO.getRuleId());
                    wxCpInterceptRule.setRuleName(entityDO.getName());
                    if(Collections3.isEmpty(matchWord)) throw new BusinessException("没有敏感词设置，请先设置！");
                    if(Collections3.isEmpty(employeeCodeList)) throw new BusinessException("请先设置企业员工信息！");
                    wxCpInterceptRule.setWordList(matchWord);
                    wxCpInterceptRule.setInterceptType(2);
                    ApplicableRange applicableRange = new ApplicableRange();
                    applicableRange.setUserList(employeeCodeList);
                    wxCpInterceptRule.setAddApplicableRange(applicableRange);
                    wxCpExternalContactService.updateInterceptRule(wxCpInterceptRule);
                    entityDO.setSyncStatus(SyncStatusEnum.SYNC_YES.getValue());
                } catch (WxErrorException ex) {
                    LogUtils.error("同步敏感词出错" + ex);
                    entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
                }
            }
            if (entityDO != null) {
                copSensitiveWordMapper.updateById(entityDO);
            }
        }
        return 1;
    }
    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(CopSensitiveWordParam param) {
        if (param == null) {
            throw new BusinessException("当前记录不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<CopSensitiveWordDO> queryWrapper = new LambdaQueryWrapper<CopSensitiveWordDO>()
                .ne(param.getId() != null, CopSensitiveWordDO::getId, param.getId())
                .eq(CopSensitiveWordDO::getName, param.getName());
        List<CopSensitiveWordDO> dos = copSensitiveWordMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的记录!");
        }
    }

    private ICopSensitiveWordService getBean(){
        return SpringBeanUtil.getBean(CopSensitiveWordServiceImpl.class);
    }
}
